import { ref, markRaw } from 'vue';
import { defineStore } from 'pinia';
import api from '@/http/api';
import tool from "@/utils/tool";
import { ElMessage } from "element-plus";

const components = import.meta.glob('@/portal/**/*.vue');
const baseRoutes = [{
  name: 'notfound',
  path: '/:pathMatch(.*)',
  text: '访问地址不存在',
  meta: {
    title: '访问地址不存在',
  },
  component: () => import('@/error/404.vue')
}, {
  name: 'portal',
  path: '/portal/:pageId',
  text: '门户',
  meta: {
    title: '门户',
  },
  component: () => import('@/portal/page/index.vue')
}];

const getComponent = async(compName, pageId, path) => {
  const keys = Object.keys(components);
  const matchKeys = keys.filter((key) => {
    return key.replace('/src/portal', '').replace('/src', '').replace('.vue', '') === path;
  });

  const component = components[matchKeys[0]];
  return !component ? null : await component().then(comp => ({
    ...comp.default,
    name: compName,
    pageId: pageId
  }));
};

const buildRouteTree = async(rootNode, children) => {
  const layoutNodeMap = {};
  await tool.asyncWalkTree({children: children}, async(child) => {
    child.name = child.name || child.id;
    const item = tool.deepClone(child);
    delete item.children;

    if (item.data && item.data.type === '页面' && item.data.pageId) {
      item.path = '/home/' + item.name + '/' + item.data.pageId;
      item.component = markRaw(await getComponent(item.name, item.data.pageId, '/home/index'));
    } else {
      item.path = item.href || item.path || '';
    }
    item.meta = item.meta || {};
    item.meta.keepAlive = (typeof item.keepAlive !== 'undefined')
      ? item.keepAlive : ((typeof item.meta.keepAlive === 'undefined') ? true : item.meta.keepAlive);
    item.meta.title = item.text;
    item.meta.hidden = item.hidden;
    item.meta.url = item.data && item.data.url;
    if (!item.component && item.path) {
      item.component = markRaw(await getComponent(item.name, item?.data?.pageId, item.path));
    }

    if (item.data && item.data.layoutPageId) {
      let layoutNode = layoutNodeMap[item.data.layoutPageId];
      if (!layoutNode) {
        layoutNode = {
          name: item.data.layoutPageId,
          path: '/home/' + item.data.layoutPageId,
          keepAlive: true,
          component: markRaw(await getComponent(item.data.layoutPageId, item.data.layoutPageId, '/home/index')),
          children: []
        };
        rootNode.push(layoutNode);
        layoutNodeMap[item.data.layoutPageId] = layoutNode;
      }
      layoutNode.children.push(item);
    } else {
      rootNode.push(item);
    }
  });
};

export const usePortalRouterStore = defineStore('portalRouter', () => {
  const menuTree = ref([]);
  const isInit = ref(false);

  const initRouter = async(router) => {
    if (isInit.value) {
      return false;
    }

    router.getRoutes().forEach(item => {
      item.name && router.removeRoute(item.name);
    });

    const res = await api.post('/business/menu/portal-tree');
    if (res.code === '500') {
      ElMessage.error(res.message);
      baseRoutes.forEach(route => router.addRoute(route));
      isInit.value = true;
      return false;
    }

    const children = res.data && res.data.children || [];
    const rootNode = [];
    await buildRouteTree(rootNode, children);
    rootNode.push(...baseRoutes);
    rootNode.forEach(route => router.addRoute(route));
    menuTree.value = filterValid(tool.deepClone(children));
    isInit.value = true;
    return true;
  };

  const filterValid = (children) => {
    tool.walkTree({children: children}, node => {
      node.children = node.children && node.children.filter(item => item.data.onlyRoute !== '1');
    });
    return children.filter(item => item.data.onlyRoute !== '1');
  };

  const getDefaultRoute = (routeList) => {
    if (!routeList || routeList.length === 0) {
      return null;
    }

    for (let route of routeList) {
      if (route.data && route.data.defaultShow === '1') {
        return route;
      }

      let temp = getDefaultRoute(route.children);
      if (temp) {
        return temp;
      }
    }

    return null;
  };

  const getFirstRoute = (routeList) => {
    if (!routeList || routeList.length === 0) {
      return null;
    }

    for (let route of routeList) {
      if (route.href || route.path) {
        return route;
      }

      let temp = getFirstRoute(route.children);
      if (temp) {
        return temp;
      }
    }

    return null;
  };

  const getShowRoute = () => {
    const route = getDefaultRoute(menuTree.value);
    return route ? route : getFirstRoute(menuTree.value);
  };

  const getMenuTree = () => {
    return menuTree.value;
  }

  return {
    initRouter,
    getMenuTree,
    getShowRoute,
  };
});

